package ua.kpi.ipsa.expert.api.client;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.rmi.RemoteException;
import java.util.List;

import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.AbstractTableModel;

import ua.kpi.ipsa.expert.api.net.Algorithm;
import ua.kpi.ipsa.expert.api.net.ConsoleException;

public class AddAlgo {
	private static String[] TITLES = new String[] { "Algorithm", "Quality",
			"Approximated time" };

	private class AlgoTableModel extends AbstractTableModel {

		@Override
		public int getRowCount() {
			return algo.size();
		}

		@Override
		public int getColumnCount() {
			return TITLES.length;
		}

		@Override
		public Object getValueAt(int row, int col) {
			Algorithm al = algo.get(row);
			return col == 0 ? al.name : col == 1 ? String.format("%.1f%%",
					al.quality * 100) : getTime(al.time);
		}

		@Override
		public String getColumnName(int column) {
			return TITLES[column];
		}
	}

	private static String getTime(long t) {
		final long MIN = 60 * 1000;
		final long HOUR = 60 * MIN;
		final long DAY = HOUR * 24;
		if (t < HOUR)
			return (t + MIN - 1) / MIN + " m";
		if (t < DAY)
			return (t + HOUR - 1) / HOUR + " h";
		return (t + DAY - 1) / DAY + " d";
	}

	private ClientFrameManager m;
	private JFrame parent;
	private int codePortionID;
	private List<Algorithm> algo;

	private JFrame f;
	private JTable table;
	private JScrollPane tableScroll;
	private JButton backBtn;
	private JButton addBtn;
	
	private ActionListener closeHandler;

	/**
	 * 
	 * @param m
	 * @param parent
	 * @param codePortionID
	 */
	public AddAlgo(ClientFrameManager m, JFrame parent, int codePortionID, ActionListener closeHandler) {
		this.m = m;
		this.parent = parent;
		this.codePortionID = codePortionID;
		this.closeHandler = closeHandler;
		try {
			algo = m.getConsole().getAvaivableAlgorithms(codePortionID);
		} catch (RemoteException e) {
			error(e);
			return;
		}
		f = m.createFrame();
		doLayout();
		f.setVisible(true);
	}

	private void doLayout() {
		f.setTitle("Add algo");
		f.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		f.addWindowListener(new WindowAdapter() {
			@Override
			public void windowClosing(WindowEvent e) {
				exit();
			}
		});
		table = new JTable(new AlgoTableModel());
		table.setAutoCreateRowSorter(true);
		table.setDefaultEditor(Object.class, null);
		table.getSelectionModel().addListSelectionListener(
				new ListSelectionListener() {

					@Override
					public void valueChanged(ListSelectionEvent e) {
						updateEnabled();
					}
				});
		tableScroll = new JScrollPane(table);
		addBtn = new JButton("Add");
		updateEnabled();
		addBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				addAlgo();
			}
		});
		backBtn = new JButton("Back");
		backBtn.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent e) {
				exit();
			}
		});

		GroupLayout g = new GroupLayout(f.getContentPane());
		f.setLayout(g);
		g.setAutoCreateContainerGaps(true);
		g.setAutoCreateGaps(true);
		g.setHorizontalGroup(g
				.createParallelGroup()
				.addComponent(tableScroll)
				.addGroup(
						g.createSequentialGroup().addComponent(backBtn)
								.addGap(0, 0, Short.MAX_VALUE)
								.addComponent(addBtn)));
		g.setVerticalGroup(g
				.createSequentialGroup()
				.addComponent(tableScroll)
				.addGroup(
						g.createParallelGroup().addComponent(backBtn)
								.addComponent(addBtn)));
		f.pack();
		f.setLocationRelativeTo(null);
	}

	private void updateEnabled() {
		addBtn.setEnabled(table.getSelectedRow() != -1);
	}

	private void exit() {
		m.disposeFrame(f);
		

		// added by evgeniy: notify parent form
		closeHandler.actionPerformed(null);
		
		parent.setVisible(true);
		
	}

	private void addAlgo() {
		int row = table.getSelectedRow();
		if (row == -1)
			return;
		try {
			m.getConsole().postAlgorithmAppointment(codePortionID,
					algo.get(row).algorithmPK);
		} catch (RemoteException | ConsoleException e) {
			error(e);
		}
		exit();
	}

	private void error(Throwable e) {
		JOptionPane.showMessageDialog(null, "Connection error", "Error",
				JOptionPane.ERROR_MESSAGE);
		e.printStackTrace();
		m.ceaseOperations();
	}
}
